Dans le cadre de la formation DSA, nous avons eu l’occasion d’analyser un jeu de données de tarification MRH à l’occasion d’un Hackathon.
Du fait des ontraintes propres au Hackathon je n’avais pas eu l’occasion de finaliser l’analyse de ce jeu de données. Par ailleurs, pour le hackathon, le choix s’était porté sur le logiciel Python.
Ce TD est donc l’occasion de poursuivre l’analyse de ce jeu de données et d’explorer l’usage de packages et d’approches développés par MV Wütrich et disponible sur le site de l’association suisse des actuaires.
Le code suivant est un ensemble d’utilitaire pour naviguer dans les répertoires relatifs du projet et installer ou charger les packages nécessaires à l’analyse :
if (!require("here")){
install.packages("here")
library("here")
}
set_here
LoadPackage <- function (load.lib=c("")) {
install.lib<-load.lib[!load.lib %in% installed.packages()]
for(lib in install.lib) install.packages(lib,dependencies=TRUE)
sapply(load.lib,require,character=TRUE)
}
LoadPackage(c('ggplot2', 'dplyr', 'formattable', 'DT', 'tidyr', 'caret', 'plotly', 'xgboost', 'flashlight', 'MetricsWeighted'))
Le jeu de données est constitué de 4 fichiers :
list.files(path=here('data', 'raw'))
## [1] "expo_test.csv" "expo_train.csv" "primes2019.csv" "sin_train.csv"
Le projet suit un portefeuille d’assurance MRH suivi sur plusieurs années de 2016 à 2018 inclus. L’objectif initial du Hackathon est d’estimer les primes 2019 sur un échantillon de contrats.
Le fichier expo_train.csv contient la liste des contrats en risques historiquement suivis :
expo_train = read.table(file = here('data', 'raw', 'expo_train.csv'), header=T, sep=',', dec='.', encoding = 'UTF-8', stringsAsFactors = F)
datatable(head(expo_train))
str(expo_train)
## 'data.frame': 155651 obs. of 19 variables:
## $ X : int 384538 441079 119668 5124 130065 450830 151401 296526 71801 360445 ...
## $ EXPO : num 1 0.825 1 1 1 ...
## $ FORMULE : chr "MEDIUM" "CONFORT" "ESSENTIEL" "ESSENTIEL" ...
## $ TYPE_RESIDENCE : chr "PRINCIPALE" "PRINCIPALE" "PRINCIPALE" "SECONDAIRE" ...
## $ TYPE_HABITATION : chr "APPARTEMENT" "MAISON" "APPARTEMENT" "MAISON" ...
## $ NB_PIECES : int 1 NA 3 2 1 2 2 2 1 3 ...
## $ SITUATION_JURIDIQUE: chr "PROPRIO" "PROPRIO" "LOCATAIRE" "LOCATAIRE" ...
## $ NIVEAU_JURIDIQUE : chr "JUR1" "JUR1" "JUR1" "JUR1" ...
## $ VALEUR_DES_BIENS : num 3500 0 35000 9000 20000 9000 20000 9000 3500 0 ...
## $ OBJETS_DE_VALEUR : chr "NIVEAU_1" "NIVEAU_1" "NIVEAU_1" "NIVEAU_1" ...
## $ ZONIER : chr "B40" "A11" "B32" "C24" ...
## $ NBSIN_TYPE1_AN1 : int 0 0 0 0 0 0 1 0 0 0 ...
## $ NBSIN_TYPE1_AN2 : int 1 1 1 1 1 1 1 1 1 1 ...
## $ NBSIN_TYPE1_AN3 : int 0 0 0 0 0 0 0 0 0 0 ...
## $ NBSIN_TYPE2_AN1 : int 0 0 0 0 0 0 0 0 0 0 ...
## $ NBSIN_TYPE2_AN2 : int 0 0 0 0 0 0 0 0 0 0 ...
## $ NBSIN_TYPE2_AN3 : int 0 0 0 0 0 0 0 0 0 0 ...
## $ id : int 5 9 11 13 14 15 20 21 28 30 ...
## $ ANNEE : int 2017 2018 2017 2018 2017 2017 2018 2016 2018 2016 ...
Les données ont été prétraitées pour disposer d’une ligne par période de risque annuelle homogène.
Pour des raisons d’anonymisation, les identifiants contrats ont été supprimés de sorte qu’il n’est pas possible de suivre l’évolution du risque d’une période sur l’autre. Pour la même raison, il ne sera pas possible dans la construction des jeux de validation et de test de s’assurer que toute l’expérience d’un même assuré est bien intégralement dans un jeu d’entraînement, de validation ou de test.
La signification des colonnes présentes est la suivante :
X:variable non nommée. Il s’agit d’un artefact du processus de création du fichier initial. On ne la prend pas en compte
EXPO :exposition en année risque du contrat. Sa valeur précalculée pour chaque ligne est comprise entre 0 et 1
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.002732 0.811475 1.000000 0.837278 1.000000 1.000000
FORMULE :variable catégorielle codant la formule du contrat comprenant 3 niveaux MEDIUM, ESSENTIEL et CONFORT
| FORMULE | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| ALL_INCLUDE | 6,671.00 | 4,759.51 | 3.65% |
| CONFORT | 87,603.00 | 73,930.57 | 56.73% |
| ESSENTIEL | 22,364.00 | 19,546.44 | 15.00% |
| MEDIUM | 39,013.00 | 32,086.59 | 24.62% |
TYPE_RESIDENCE :variable catégorielle codant le fait que le bien est une résidence PRINCIPALE, ou SECONDAIRE
| TYPE_RESIDENCE | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| PRINCIPALE | 130,727.00 | 112,793.55 | 86.55% |
| SECONDAIRE | 24,924.00 | 17,529.57 | 13.45% |
TYPE_HABITATION :variable catégorielle codant le fait que le bien est un APPARTEMENT, ou une MAISON
| TYPE_HABITATION | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| APPARTEMENT | 71,123.00 | 61,562.82 | 47.24% |
| MAISON | 84,528.00 | 68,760.30 | 52.76% |
NB_PIECES :variable numérique indiquant le nombre de pièces du logement
| NB_PIECES | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| 0 | 3,718.00 | 2,413.72 | 1.85% |
| 1 | 40,300.00 | 31,943.51 | 24.51% |
| 2 | 60,973.00 | 51,931.99 | 39.85% |
| 3 | 31,695.00 | 27,730.87 | 21.28% |
| 4 | 9,615.00 | 8,495.12 | 6.52% |
| NA | 9,350.00 | 7,807.90 | 5.99% |
SITUATION_JURIDIQUE :variable catégorielle indiquant si le souscripteur est prorpiétaire (PROPRIO) ou locataire (LOCATAIRE) du logement assuré
| SITUATION_JURIDIQUE | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| LOCATAIRE | 86,421.00 | 76,135.03 | 58.42% |
| PROPRIO | 69,230.00 | 54,188.09 | 41.58% |
NIVEAU_JURIDIQUE :variable catégorielle codant le niveau de couverture de la garantie juridique
| NIVEAU_JURIDIQUE | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| JUR1 | 153,568.00 | 128,854.03 | 98.87% |
| JUR2 | 2,083.00 | 1,469.09 | 1.13% |
VALEUR_DES_BIENS :variable numérique reflétant la valeur couverte du contenu du logement
| VALEUR_DES_BIENS | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| 0 | 8,307.00 | 5,259.05 | 4.04% |
| 3500 | 51,879.00 | 40,929.10 | 31.41% |
| 9000 | 34,770.00 | 30,059.53 | 23.07% |
| 20000 | 33,745.00 | 29,664.65 | 22.76% |
| 35000 | 11,528.00 | 10,299.00 | 7.90% |
| 50000 | 7,944.00 | 7,243.56 | 5.56% |
| 80000 | 6,534.00 | 6,018.46 | 4.62% |
| 100000 | 944.00 | 849.77 | 0.65% |
OBJETS_DE_VALEUR :variable catégorielle codant le niveau de couverture des objets
| OBJETS_DE_VALEUR | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| NIVEAU_1 | 145,959.00 | 121,738.34 | 93.41% |
| NIVEAU_2 | 9,692.00 | 8,584.78 | 6.59% |
ZONIER :variable catégorielle codant la zone du bien assuré. Le code est constitué d’une lettre représentant une zone et d’un nombre représentant une partie de la zone
| ZONIER | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| A1 | 1,822.00 | 1,579.15 | 1.21% |
| A10 | 1,125.00 | 963.04 | 0.74% |
| A11 | 4,775.00 | 4,140.40 | 3.18% |
| A12 | 3,115.00 | 2,694.44 | 2.07% |
| A13 | 1,879.00 | 1,593.61 | 1.22% |
| A14 | 828.00 | 695.12 | 0.53% |
| A2 | 1,750.00 | 1,466.96 | 1.13% |
| A3 | 1,129.00 | 975.75 | 0.75% |
| A4 | 81.00 | 62.13 | 0.05% |
| A5 | 16.00 | 14.27 | 0.01% |
| A6 | 698.00 | 610.63 | 0.47% |
| A7 | 256.00 | 222.42 | 0.17% |
| A8 | 66.00 | 61.27 | 0.05% |
| A9 | 4,082.00 | 3,526.65 | 2.71% |
| B1 | 793.00 | 701.39 | 0.54% |
| B10 | 3,520.00 | 3,005.74 | 2.31% |
| B11 | 11.00 | 8.94 | 0.01% |
| B12 | 342.00 | 289.71 | 0.22% |
| B13 | 44.00 | 37.32 | 0.03% |
| B14 | 116.00 | 98.55 | 0.08% |
| B16 | 211.00 | 185.81 | 0.14% |
| B17 | 3,530.00 | 2,992.31 | 2.30% |
| B18 | 8.00 | 6.25 | 0.00% |
| B19 | 950.00 | 800.99 | 0.61% |
| B2 | 438.00 | 385.83 | 0.30% |
| B20 | 6.00 | 5.58 | 0.00% |
| B21 | 44.00 | 37.82 | 0.03% |
| B22 | 59.00 | 52.15 | 0.04% |
| B23 | 214.00 | 183.13 | 0.14% |
| B24 | 135.00 | 118.09 | 0.09% |
| B25 | 641.00 | 551.08 | 0.42% |
| B26 | 1,477.00 | 1,264.44 | 0.97% |
| B27 | 188.00 | 167.93 | 0.13% |
| B28 | 268.00 | 228.86 | 0.18% |
| B29 | 4,269.00 | 3,645.34 | 2.80% |
| B3 | 1,956.00 | 1,691.09 | 1.30% |
| B30 | 506.00 | 443.22 | 0.34% |
| B31 | 79.00 | 71.24 | 0.05% |
| B32 | 7,015.00 | 5,906.43 | 4.53% |
| B33 | 186.00 | 167.03 | 0.13% |
| B34 | 708.00 | 616.63 | 0.47% |
| B35 | 3.00 | 2.28 | 0.00% |
| B36 | 454.00 | 377.39 | 0.29% |
| B37 | 150.00 | 126.09 | 0.10% |
| B38 | 85.00 | 70.05 | 0.05% |
| B39 | 2,543.00 | 2,159.86 | 1.66% |
| B4 | 1,868.00 | 1,603.70 | 1.23% |
| B40 | 5,776.00 | 4,859.50 | 3.73% |
| B41 | 402.00 | 341.69 | 0.26% |
| B42 | 29.00 | 25.69 | 0.02% |
| B43 | 6,038.00 | 5,066.02 | 3.89% |
| B44 | 6.00 | 5.09 | 0.00% |
| B45 | 452.00 | 379.98 | 0.29% |
| B5 | 34.00 | 30.47 | 0.02% |
| B6 | 122.00 | 105.72 | 0.08% |
| B7 | 353.00 | 303.13 | 0.23% |
| B8 | 239.00 | 214.63 | 0.16% |
| B9 | 608.00 | 519.74 | 0.40% |
| C1 | 2,760.00 | 2,325.40 | 1.78% |
| C10 | 899.00 | 723.85 | 0.56% |
| C11 | 1,322.00 | 1,067.75 | 0.82% |
| C12 | 2,453.00 | 1,917.28 | 1.47% |
| C13 | 1,236.00 | 959.28 | 0.74% |
| C14 | 1,372.00 | 1,095.67 | 0.84% |
| C15 | 1,202.00 | 947.23 | 0.73% |
| C16 | 1,272.00 | 998.16 | 0.77% |
| C17 | 845.00 | 656.75 | 0.50% |
| C18 | 739.00 | 605.29 | 0.46% |
| C19 | 2,897.00 | 2,317.49 | 1.78% |
| C2 | 6,067.00 | 5,172.98 | 3.97% |
| C20 | 14,581.00 | 12,217.25 | 9.37% |
| C21 | 4,816.00 | 4,002.97 | 3.07% |
| C22 | 2,555.00 | 2,050.02 | 1.57% |
| C23 | 6,214.00 | 5,119.00 | 3.93% |
| C24 | 1,972.00 | 1,621.60 | 1.24% |
| C3 | 3,041.00 | 2,571.18 | 1.97% |
| C4 | 1,713.00 | 1,444.03 | 1.11% |
| C5 | 6,833.00 | 5,665.22 | 4.35% |
| C6 | 5,176.00 | 4,382.99 | 3.36% |
| C7 | 2,103.00 | 1,736.06 | 1.33% |
| C8 | 5,550.00 | 4,455.87 | 3.42% |
| C9 | 9,535.00 | 7,810.05 | 5.99% |
NBSIN_TYPE1_AN1 :variable numérique indiquant le nombre de sinistre de type 1 l’année précédente
| NBSIN_TYPE1_AN1 | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| 0 | 145,434.00 | 121,118.77 | 92.94% |
| 1 | 9,378.00 | 8,465.38 | 6.50% |
| 2 | 765.00 | 676.86 | 0.52% |
| 3 | 74.00 | 62.11 | 0.05% |
NBSIN_TYPE1_AN2 :variable numérique indiquant le nombre de sinistre de type 1 il y a 2 ans
ATTENTION : comme la table ci-dessous le démontre, cette variable présente un problème puisque toutes les lignes ont au moins un sinistre
Comme discuté dans le hackathon on ignore cette variable
| NBSIN_TYPE1_AN2 | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| 1 | 146,676.00 | 122,175.11 | 93.75% |
| 2 | 8,225.00 | 7,462.01 | 5.73% |
| 3 | 750.00 | 685.99 | 0.53% |
NBSIN_TYPE1_AN3 :variable numérique indiquant le nombre de sinistre de type 1 il y a 3 ans
| NBSIN_TYPE1_AN3 | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| 0 | 147,569.00 | 122,889.56 | 94.30% |
| 1 | 7,403.00 | 6,807.03 | 5.22% |
| 2 | 625.00 | 576.62 | 0.44% |
| 3 | 54.00 | 49.91 | 0.04% |
NBSIN_TYPE2_AN1 :variable numérique indiquant le nombre de sinistre de type 2 l’année précédente
| NBSIN_TYPE2_AN1 | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| 0 | 152,587.00 | 127,610.08 | 97.92% |
| 1 | 2,870.00 | 2,540.14 | 1.95% |
| 2 | 180.00 | 159.97 | 0.12% |
| 3 | 14.00 | 12.93 | 0.01% |
NBSIN_TYPE2_AN2 :variable numérique indiquant le nombre de sinistre de type 2 il y a 2 ans
| NBSIN_TYPE2_AN2 | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| 0 | 136,330.00 | 114,011.30 | 87.48% |
| 1 | 2,058.00 | 1,861.63 | 1.43% |
| 2 | 113.00 | 103.72 | 0.08% |
| 3 | 8.00 | 8.00 | 0.01% |
| NA | 17,142.00 | 14,338.46 | 11.00% |
NBSIN_TYPE2_AN3 :variable numérique indiquant le nombre de sinistre de type 2 il y a 3 ans
| NBSIN_TYPE2_AN3 | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| 0 | 153,501.00 | 128,360.07 | 98.49% |
| 1 | 2,019.00 | 1,844.33 | 1.42% |
| 2 | 125.00 | 113.36 | 0.09% |
| 3 | 6.00 | 5.37 | 0.00% |
id :identifiant du risque, clef de jointure
ANNEE :variable catégorielle indiquant l’année d’observation du risque : 2016, 2017, 2018
| ANNEE | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|
| 2016 | 54,283.00 | 45,171.85 | 34.66% |
| 2017 | 52,053.00 | 43,654.97 | 33.50% |
| 2018 | 49,315.00 | 41,496.30 | 31.84% |
Le fichier expo_train.csv contient la liste des contrats en risques historiquement suivis :
sin_train = read.table(file = here('data', 'raw', 'sin_train.csv'), header=T, sep=';', dec=',', encoding = 'UTF-8', stringsAsFactors = F)
datatable(head(sin_train))
str(sin_train)
## 'data.frame': 2693 obs. of 4 variables:
## $ id : int 15 277 643 668 730 1816 1852 2061 2270 2322 ...
## $ NB : int 1 1 1 1 1 1 1 1 1 1 ...
## $ COUT : num 521.4 3000.2 26.3 462.4 640.9 ...
## $ ANNEE: int 2017 2016 2018 2017 2018 2018 2016 2018 2018 2017 ...
id : identifiant du risque, clef de jointure avec le fichier expo_train
NB : Nombre de sinistres de la typologie modélisée (inconnue) sur la période d’observation
| NB | nb_lignes |
|---|---|
| 1 | 2,613.00 |
| 2 | 79.00 |
| 3 | 1.00 |
On peut désormais combine les information d’exposition et de sinistres :
mrh <- expo_train %>%
left_join(sin_train, by =c('id','ANNEE')) %>%
replace_na(list('NB'=0, 'COUT'=0))
N’ayant pas accèsau fichier de test utilisé lors du KAckathon, on dissocie ici le fichier mrh en un fichier train (70%), un fichier val (20%) et un fichier test (10%)
set.seed(42)
trainIndex<- createDataPartition(mrh$NB>=0, p=.7, list=FALSE, time=1)
mrh_train<-mrh[trainIndex,]
mrh_test<-mrh[ -trainIndex,]
valIndex<- createDataPartition(mrh_test$NB>=0, p=.66, list=FALSE, time=1)
mrh_val<-mrh_test[ valIndex,]
mrh_test<-mrh_test[ -valIndex,]
tx <- sum(mrh_train$NB*mrh_train$EXPO)/sum(mrh_train$EXPO)
print(paste0('taux de sinistre moyen annuel : ', round(tx * 100,2), '%'))
## [1] "taux de sinistre moyen annuel : 1.96%"
| FORMULE | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| ALL_INCLUDE | 0.57% | 4,695.00 | 3,355.67 | 3.67% |
| CONFORT | 2.11% | 61,372.00 | 51,858.85 | 56.79% |
| ESSENTIEL | 2.22% | 15,555.00 | 13,597.27 | 14.89% |
| MEDIUM | 1.69% | 27,334.00 | 22,501.75 | 24.64% |
ENSEIGNEMENT : Le comportement observé est stable dans le temps. Les niveaux CONFORT et ESSENTIEL semblent avoir un niveau de risque de fréquence équivalent
| TYPE_RESIDENCE | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| PRINCIPALE | 2.15% | 91,410.00 | 78,937.92 | 86.45% |
| SECONDAIRE | 0.75% | 17,546.00 | 12,375.63 | 13.55% |
ENSEIGNEMENT : Le comportement observé est stable dans le temps. Les résidences SECONDAIRE ont systématiquement une fréquence moindre
| TYPE_HABITATION | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| APPARTEMENT | 1.98% | 49,749.00 | 43,093.59 | 47.19% |
| MAISON | 1.95% | 59,207.00 | 48,219.96 | 52.81% |
ENSEIGNEMENT : Le comportement observé N’est PAS stable dans le temps. Le type d’habitation est à exclure.
| NB_PIECES | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| 0 | 0.12% | 2,610.00 | 1,715.52 | 1.88% |
| 1 | 1.61% | 28,256.00 | 22,425.90 | 24.56% |
| 2 | 1.83% | 42,724.00 | 36,390.78 | 39.85% |
| 3 | 2.48% | 22,181.00 | 19,440.34 | 21.29% |
| 4 | 2.95% | 6,639.00 | 5,879.31 | 6.44% |
| NA | 1.98% | 6,546.00 | 5,461.69 | 5.98% |
ENSEIGNEMENT : Le NB_PIECES présente des valeurs manquantes. La fréquence tend à augmenter avec le nombre de pièces.
| SITUATION_JURIDIQUE | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| LOCATAIRE | 2.21% | 60,339.00 | 53,225.98 | 58.29% |
| PROPRIO | 1.63% | 48,617.00 | 38,087.57 | 41.71% |
ENSEIGNEMENT : Les propriétaires semblent avoir un fréquence moindre que les locataires de manière consistante, mais avec de la variabilité.
| NIVEAU_JURIDIQUE | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| JUR1 | 1.97% | 107,497.00 | 90,273.20 | 98.86% |
| JUR2 | 1.52% | 1,459.00 | 1,040.35 | 1.14% |
ENSEIGNEMENT : Le NIVEAU_JURIDIQUE N’est PAS stable dans le temps. A exclure.
| VALEUR_DES_BIENS | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| 0 | 0.25% | 5,782.00 | 3,682.96 | 4.03% |
| 3500 | 1.36% | 36,543.00 | 28,888.32 | 31.64% |
| 9000 | 1.95% | 24,283.00 | 21,014.51 | 23.01% |
| 20000 | 2.25% | 23,639.00 | 20,768.83 | 22.74% |
| 35000 | 2.86% | 8,047.00 | 7,187.60 | 7.87% |
| 50000 | 3.14% | 5,470.00 | 4,991.12 | 5.47% |
| 80000 | 3.09% | 4,557.00 | 4,210.03 | 4.61% |
| 100000 | 3.72% | 635.00 | 570.18 | 0.62% |
ENSEIGNEMENT : La fréquence augmente globalement avec la valeur des biens selon une relation non linéaire
| OBJETS_DE_VALEUR | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| NIVEAU_1 | 1.84% | 102,196.00 | 85,308.12 | 93.42% |
| NIVEAU_2 | 3.77% | 6,760.00 | 6,005.44 | 6.58% |
ENSEIGNEMENT : Le NIVEAU_2 présente une fréquence significativement plus élevée.
| ZONIER | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| A1 | 1.75% | 1,271.00 | 1,098.88 | 1.20% |
| A10 | 1.21% | 768.00 | 659.36 | 0.72% |
| A11 | 0.62% | 3,349.00 | 2,901.64 | 3.18% |
| A12 | 1.10% | 2,182.00 | 1,896.53 | 2.08% |
| A13 | 0.97% | 1,326.00 | 1,112.93 | 1.22% |
| A14 | 1.81% | 596.00 | 497.59 | 0.54% |
| A2 | 1.14% | 1,199.00 | 1,004.07 | 1.10% |
| A3 | 0.57% | 814.00 | 705.81 | 0.77% |
| A4 | 0.00% | 55.00 | 40.92 | 0.04% |
| A5 | 0.00% | 11.00 | 10.24 | 0.01% |
| A6 | 0.72% | 495.00 | 427.35 | 0.47% |
| A7 | 0.69% | 170.00 | 145.53 | 0.16% |
| A8 | 2.29% | 48.00 | 43.73 | 0.05% |
| A9 | 0.56% | 2,885.00 | 2,488.88 | 2.73% |
| B1 | 0.41% | 556.00 | 492.90 | 0.54% |
| B10 | 1.72% | 2,492.00 | 2,140.03 | 2.34% |
| B11 | 0.00% | 6.00 | 4.80 | 0.01% |
| B12 | 2.37% | 249.00 | 210.74 | 0.23% |
| B13 | 6.23% | 37.00 | 32.09 | 0.04% |
| B14 | 0.00% | 83.00 | 69.97 | 0.08% |
| B16 | 0.76% | 147.00 | 130.79 | 0.14% |
| B17 | 1.79% | 2,442.00 | 2,071.38 | 2.27% |
| B18 | 0.00% | 6.00 | 4.25 | 0.00% |
| B19 | 2.42% | 672.00 | 572.48 | 0.63% |
| B2 | 1.09% | 308.00 | 274.89 | 0.30% |
| B20 | 0.00% | 6.00 | 5.58 | 0.01% |
| B21 | 0.00% | 30.00 | 25.92 | 0.03% |
| B22 | 0.00% | 41.00 | 36.37 | 0.04% |
| B23 | 0.78% | 150.00 | 128.79 | 0.14% |
| B24 | 2.56% | 91.00 | 78.21 | 0.09% |
| B25 | 1.33% | 436.00 | 375.81 | 0.41% |
| B26 | 1.24% | 1,031.00 | 884.64 | 0.97% |
| B27 | 0.84% | 133.00 | 119.69 | 0.13% |
| B28 | 1.35% | 173.00 | 148.10 | 0.16% |
| B29 | 1.83% | 2,979.00 | 2,541.22 | 2.78% |
| B3 | 0.75% | 1,394.00 | 1,210.68 | 1.33% |
| B30 | 0.96% | 355.00 | 310.94 | 0.34% |
| B31 | 0.00% | 56.00 | 51.74 | 0.06% |
| B32 | 1.81% | 4,913.00 | 4,134.65 | 4.53% |
| B33 | 0.85% | 134.00 | 117.90 | 0.13% |
| B34 | 1.23% | 518.00 | 446.21 | 0.49% |
| B35 | 0.00% | 3.00 | 2.28 | 0.00% |
| B36 | 1.33% | 319.00 | 266.18 | 0.29% |
| B37 | 0.00% | 108.00 | 94.32 | 0.10% |
| B38 | 5.38% | 67.00 | 55.78 | 0.06% |
| B39 | 1.37% | 1,804.00 | 1,542.57 | 1.69% |
| B4 | 0.73% | 1,324.00 | 1,134.45 | 1.24% |
| B40 | 2.41% | 4,045.00 | 3,427.84 | 3.75% |
| B41 | 2.79% | 282.00 | 242.19 | 0.27% |
| B42 | 0.00% | 22.00 | 20.55 | 0.02% |
| B43 | 1.72% | 4,229.00 | 3,553.62 | 3.89% |
| B44 | 0.00% | 5.00 | 4.09 | 0.00% |
| B45 | 0.83% | 317.00 | 268.14 | 0.29% |
| B5 | 0.00% | 24.00 | 20.47 | 0.02% |
| B6 | 1.30% | 91.00 | 77.15 | 0.08% |
| B7 | 2.84% | 243.00 | 211.00 | 0.23% |
| B8 | 0.00% | 152.00 | 136.97 | 0.15% |
| B9 | 1.93% | 437.00 | 374.18 | 0.41% |
| C1 | 2.68% | 1,923.00 | 1,619.36 | 1.77% |
| C10 | 2.92% | 638.00 | 515.30 | 0.56% |
| C11 | 3.19% | 906.00 | 739.61 | 0.81% |
| C12 | 3.71% | 1,700.00 | 1,335.15 | 1.46% |
| C13 | 2.09% | 882.00 | 681.10 | 0.75% |
| C14 | 2.77% | 962.00 | 769.95 | 0.84% |
| C15 | 3.70% | 851.00 | 666.75 | 0.73% |
| C16 | 2.56% | 894.00 | 707.78 | 0.78% |
| C17 | 2.18% | 592.00 | 463.76 | 0.51% |
| C18 | 1.85% | 526.00 | 429.41 | 0.47% |
| C19 | 3.29% | 2,006.00 | 1,607.93 | 1.76% |
| C2 | 2.34% | 4,216.00 | 3,597.31 | 3.94% |
| C20 | 3.06% | 10,231.00 | 8,576.45 | 9.39% |
| C21 | 1.62% | 3,365.00 | 2,789.43 | 3.05% |
| C22 | 1.50% | 1,789.00 | 1,430.49 | 1.57% |
| C23 | 2.15% | 4,418.00 | 3,642.23 | 3.99% |
| C24 | 1.91% | 1,360.00 | 1,122.90 | 1.23% |
| C3 | 1.18% | 2,127.00 | 1,817.00 | 1.99% |
| C4 | 3.82% | 1,174.00 | 974.79 | 1.07% |
| C5 | 1.79% | 4,772.00 | 3,952.35 | 4.33% |
| C6 | 1.59% | 3,614.00 | 3,073.13 | 3.37% |
| C7 | 2.10% | 1,442.00 | 1,195.34 | 1.31% |
| C8 | 1.65% | 3,845.00 | 3,081.29 | 3.37% |
| C9 | 2.93% | 6,644.00 | 5,438.74 | 5.96% |
ENSEIGNEMENT : Le ZONIER présente une fréquence avec beaucoup de variabilité, mais il semble y avoir une croissance par région qu’on peut tester :
| REGION | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| A | 0.92% | 15,169.00 | 13,033.47 | 14.27% |
| B | 1.66% | 32,910.00 | 28,052.53 | 30.72% |
| C | 2.40% | 60,877.00 | 50,227.55 | 55.01% |
| NBSIN_TYPE1_AN1 | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| 0 | 1.83% | 101,793.00 | 84,856.05 | 92.93% |
| 1 | 3.70% | 6,581.00 | 5,945.96 | 6.51% |
| 2 | 4.04% | 530.00 | 469.28 | 0.51% |
| 3 | 9.46% | 52.00 | 42.26 | 0.05% |
ENSEIGNEMENT : La fréquence augmente globalement avec le nombre de sinistres de type 1 l’année précédente. Toutefois, il semble surtout q’il existe un effet d’une indicatrice a eu sinistre ou non.
| NBSIN_TYPE1_AN3 | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| 0 | 1.86% | 103,309.00 | 86,105.62 | 94.30% |
| 1 | 3.42% | 5,171.00 | 4,767.33 | 5.22% |
| 2 | 6.13% | 435.00 | 403.13 | 0.44% |
| 3 | 5.34% | 41.00 | 37.46 | 0.04% |
ENSEIGNEMENT : La fréquence augmente globalement avec le nombre de sinistres de type 1 il y a 3 ans. Toutefois, il semble surtout q’il existe un effet d’une indicatrice a eu sinistre ou non.
| NBSIN_TYPE2_AN1 | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| 0 | 1.95% | 106,796.00 | 89,403.29 | 97.91% |
| 1 | 2.61% | 2,034.00 | 1,797.95 | 1.97% |
| 2 | 2.93% | 115.00 | 102.38 | 0.11% |
| 3 | 0.00% | 11.00 | 9.93 | 0.01% |
ENSEIGNEMENT : Il n’existe pas de lien stable sur la fréquence. A ne pas retenir.
| NBSIN_TYPE2_AN2 | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| 0 | 1.96% | 95,382.00 | 79,861.28 | 87.46% |
| 1 | 3.02% | 1,452.00 | 1,307.09 | 1.43% |
| 2 | 1.39% | 77.00 | 71.91 | 0.08% |
| 3 | 0.00% | 3.00 | 3.00 | 0.00% |
| NA | 1.86% | 12,042.00 | 10,070.27 | 11.03% |
ENSEIGNEMENT : Il n’existe pas de lien stable sur la fréquence. A ne pas retenir.
| NBSIN_TYPE2_AN3 | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| 0 | 1.95% | 107,445.00 | 89,931.57 | 98.49% |
| 1 | 2.68% | 1,414.00 | 1,292.12 | 1.42% |
| 2 | 4.31% | 93.00 | 85.86 | 0.09% |
| 3 | 0.00% | 4.00 | 4.00 | 0.00% |
ENSEIGNEMENT : Il n’existe pas de lien stable sur la fréquence. A ne pas retenir.
| ANNEE | Freq | nb_lignes | EXPO | pct_EXPO |
|---|---|---|---|---|
| 2016 | 1.82% | 37,947.00 | 31,635.56 | 34.64% |
| 2017 | 2.04% | 36,440.00 | 30,597.37 | 33.51% |
| 2018 | 2.04% | 34,569.00 | 29,080.62 | 31.85% |
ENSEIGNEMENT : L’année 2016 semble atypique. Le niveau actuel semble plus proche de ceux de 2017 et 2018.
Dans cette partie, on essaye de modéliser la fréquence des sinistres.
On commence par une modélisation de référence qui consistera en un modèle GLM Poisson classique en tirant partie des enseignements de la partie précédente.
preprocess<- function(dt) {
res <- dt %>%
mutate(
NB_PIECES = ifelse(is.na(NB_PIECES), 2, NB_PIECES), #2 est le mode de NB_PIECES
NBSIN_TYPE1_AN1 = ifelse(NBSIN_TYPE1_AN1==0,0,1), #On regroupe les modalités non stables dans le temps
NBSIN_TYPE1_AN3 = ifelse(NBSIN_TYPE1_AN3==0,0,1), #On regroupe les modalités non stables dans le temps
REGION = gsub('[0-9]', '', ZONIER) #création de région
) %>%
select(-c('X', 'TYPE_HABITATION', 'NIVEAU_JURIDIQUE', 'NBSIN_TYPE1_AN2', 'NBSIN_TYPE2_AN1', 'NBSIN_TYPE2_AN2', 'NBSIN_TYPE2_AN3' )) %>% # On supprime les variables sans lien stable dans le temps
relocate('id', 'EXPO', 'FORMULE', 'TYPE_RESIDENCE', 'SITUATION_JURIDIQUE', 'OBJETS_DE_VALEUR', 'VALEUR_DES_BIENS', 'NB_PIECES', 'ZONIER', 'REGION', 'NBSIN_TYPE1_AN1', 'NBSIN_TYPE1_AN3', 'ANNEE', 'NB', 'COUT' )
return(res)
}
df_train <- preprocess(mrh_train)
df_val <- preprocess(mrh_val)
df_test <- preprocess(mrh_test)
reg0 = glm(NB~1+offset(log(EXPO)),family=poisson,data=df_train)
summary(reg0)
##
## Call:
## glm(formula = NB ~ 1 + offset(log(EXPO)), family = poisson, data = df_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.2058 -0.2058 -0.2058 -0.1774 4.8750
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -3.85523 0.02274 -169.5 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 15507 on 108955 degrees of freedom
## Residual deviance: 15507 on 108955 degrees of freedom
## AIC: 19294
##
## Number of Fisher Scoring iterations: 6
plot(reg0)
fit_glm <- glm(NB ~ FORMULE + TYPE_RESIDENCE + SITUATION_JURIDIQUE + OBJETS_DE_VALEUR + as.factor(VALEUR_DES_BIENS) + as.factor(NB_PIECES) + REGION + as.factor(NBSIN_TYPE1_AN1) + as.factor(NBSIN_TYPE1_AN3) + as.factor(ANNEE),
data=df_train, offset=log(EXPO), family=quasipoisson())
summary(fit_glm)
##
## Call:
## glm(formula = NB ~ FORMULE + TYPE_RESIDENCE + SITUATION_JURIDIQUE +
## OBJETS_DE_VALEUR + as.factor(VALEUR_DES_BIENS) + as.factor(NB_PIECES) +
## REGION + as.factor(NBSIN_TYPE1_AN1) + as.factor(NBSIN_TYPE1_AN3) +
## as.factor(ANNEE), family = quasipoisson(), data = df_train,
## offset = log(EXPO))
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.4944 -0.2199 -0.1767 -0.1221 4.3198
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -8.35092 0.78731 -10.607 < 2e-16 ***
## FORMULECONFORT 0.89236 0.21816 4.090 4.31e-05 ***
## FORMULEESSENTIEL 0.85689 0.22565 3.798 0.000146 ***
## FORMULEMEDIUM 0.85491 0.21928 3.899 9.67e-05 ***
## TYPE_RESIDENCESECONDAIRE -0.61505 0.11032 -5.575 2.48e-08 ***
## SITUATION_JURIDIQUEPROPRIO -0.05789 0.06008 -0.963 0.335315
## OBJETS_DE_VALEURNIVEAU_2 0.28047 0.08372 3.350 0.000808 ***
## as.factor(VALEUR_DES_BIENS)3500 0.62766 0.34944 1.796 0.072467 .
## as.factor(VALEUR_DES_BIENS)9000 0.77136 0.35190 2.192 0.028381 *
## as.factor(VALEUR_DES_BIENS)20000 0.83321 0.35253 2.364 0.018103 *
## as.factor(VALEUR_DES_BIENS)35000 0.97408 0.35808 2.720 0.006523 **
## as.factor(VALEUR_DES_BIENS)50000 0.98658 0.36156 2.729 0.006360 **
## as.factor(VALEUR_DES_BIENS)80000 0.84862 0.36617 2.318 0.020477 *
## as.factor(VALEUR_DES_BIENS)1e+05 0.92804 0.42120 2.203 0.027574 *
## as.factor(NB_PIECES)1 2.04091 0.82752 2.466 0.013653 *
## as.factor(NB_PIECES)2 1.98259 0.82633 2.399 0.016430 *
## as.factor(NB_PIECES)3 2.23114 0.82809 2.694 0.007054 **
## as.factor(NB_PIECES)4 2.32381 0.83140 2.795 0.005190 **
## REGIONB 0.43795 0.10544 4.154 3.27e-05 ***
## REGIONC 0.95079 0.09975 9.532 < 2e-16 ***
## as.factor(NBSIN_TYPE1_AN1)1 0.43828 0.07264 6.034 1.61e-09 ***
## as.factor(NBSIN_TYPE1_AN3)1 0.33269 0.08157 4.078 4.54e-05 ***
## as.factor(ANNEE)2017 0.10300 0.05889 1.749 0.080290 .
## as.factor(ANNEE)2018 0.10260 0.05960 1.721 0.085171 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for quasipoisson family taken to be 1.119526)
##
## Null deviance: 15507 on 108955 degrees of freedom
## Residual deviance: 14905 on 108932 degrees of freedom
## AIC: NA
##
## Number of Fisher Scoring iterations: 9
plot(fit_glm)
x <- c('FORMULE', 'TYPE_RESIDENCE', 'SITUATION_JURIDIQUE','OBJETS_DE_VALEUR', 'VALEUR_DES_BIENS', 'NB_PIECES', 'REGION', 'NBSIN_TYPE1_AN1', 'NBSIN_TYPE1_AN3', 'ANNEE')
y <- 'NB'
w <- 'EXPO'
# Input maker
prep_xgb <- function(dat, x) {
data.matrix(dat[, x, drop = FALSE])
}
# Data interface to XGBoost
dtrain <- xgb.DMatrix(
prep_xgb(df_train, x),
label = df_train[[y]],
weight = df_train[[w]]
)
# Parameters chosen by 5-fold grouped CV
params_freq <- list(
learning_rate = 0.2,
max_depth = 5,
alpha = 3,
lambda = 0.5,
max_delta_step = 2,
min_split_loss = 0,
# monotone_constraints = c(0,-1,0,0,0,0,0),
# interaction_constraints = list(4, c(0, 1, 2, 3, 5, 6)),
colsample_bytree = 1,
subsample = 0.9
)
# Fit
set.seed(1)
fit_xgb <- xgb.train(
params_freq,
data = dtrain,
nrounds = 580,
objective = "count:poisson",
watchlist = list(train = dtrain),
print_every_n = 100
)
## [1] train-poisson-nloglik:0.501726
## [101] train-poisson-nloglik:0.108273
## [201] train-poisson-nloglik:0.093639
## [301] train-poisson-nloglik:0.092993
## [401] train-poisson-nloglik:0.092593
## [501] train-poisson-nloglik:0.092233
## [580] train-poisson-nloglik:0.091997
# Save and load model
xgb.save(fit_xgb, "xgb.model")
## [1] TRUE
fit_xgb <- xgb.load("xgb.model")
The models are ready, so let’s shed light into them.
We start by setting up the explainers. These are basically objects that know how to create predictions.
Crucial: the prediction function needs to work for subsets of datasets, not just for the original model data set.
fl_glm <- flashlight(
model = fit_glm, label = "GLM",
predict_function = function(fit, X) predict(fit, X, type = "response")
)
fl_xgb <- flashlight(
model = fit_xgb, label = "XGBoost",
predict_function = function(fit, X) predict(fit, prep_xgb(X, x))
)
# Combine them and add common elements like reference data
metrics <- list(`Average deviance` = deviance_poisson,
`Relative deviance reduction` = r_squared_poisson)
fls <- multiflashlight(list(fl_glm, fl_xgb), data = df_val,
y = y, w = w, metrics = metrics)
# Version on canonical scale
fls_log <- multiflashlight(fls, linkinv = log)
We start to interpret the models by looking at model performance using deviance related metrics.
fillc <- "#E69F00"
perf <- light_performance(fls)
perf
##
## I am an object of class light_performance_multi
##
## data.frames:
##
## data
## # A tibble: 4 x 3
## label metric value
## <fct> <fct> <dbl>
## 1 GLM Average deviance 0.151
## 2 GLM Relative deviance reduction 0.0506
## 3 XGBoost Average deviance 0.152
## 4 XGBoost Relative deviance reduction 0.0454
plot(perf, geom = "point") +
labs(x = element_blank(), y = element_blank())
Next, we consider permutation variable importance. By default flashlight uses the first performance metric specified above.
imp <- light_importance(fls, v = x)
plot(imp, fill = fillc, color = "black")
Taking the average of many ICE curves produces the famous partial dependence plot. We consider such plots for four predictors.
plot(light_profile(fls, v = "VALEUR_DES_BIENS"))
plot(light_profile(fls, v = "NB_PIECES"))
plot(light_profile(fls, v = "TYPE_RESIDENCE"))
Classic predicted/residual/response versus covariable plots are worth a look.
# Average predicted versus covariable
plot(light_profile(fls, v = "NB_PIECES", type = "predicted"))
# Average residual versus covariable
plot(light_profile(fls, v = "NB_PIECES", type = "residual")) +
geom_hline(yintercept = 0)
# Average response versus covariable
plot(light_profile(fls, v = "NB_PIECES", type = "response"))
We often get a good picture of the effect of a covariable by combining partial dependence with classic plots.
eff_DrivAge <- light_effects(fls, v = "NB_PIECES", counts_weighted = TRUE)
p <- plot(eff_DrivAge, show_points = FALSE)
plot_counts(p, eff_DrivAge, alpha = 0.3)
interact_rel <- light_interaction(
fls_log,
v = most_important(imp, 4),
take_sqrt = FALSE,
pairwise = TRUE,
use_linkinv = TRUE,
seed = 61
)
plot(interact_rel, color = "black", fill = fillc, rotate_x = TRUE)
interact_abs <- light_interaction(
fls_log,
v = most_important(imp, 4),
normalize = FALSE,
pairwise = TRUE,
use_linkinv = TRUE,
seed = 61
)
plot(interact_abs, color = "black", fill = fillc, rotate_x = TRUE)
Let’s illustrate a strong and a weak interaction by conditional partial dependence plots.
# Strong interaction
# p <- plot(eff_DrivAge, show_points = FALSE)
# plot_counts(p, eff_DrivAge, alpha = 0.3)
pdp_NBPIECES_REGION <- light_profile(fls_log, v = "NB_PIECES", by = "REGION",
pd_seed = 50, data = df_val, counts_weighted=TRUE)
p <- plot(pdp_NBPIECES_REGION, show_points = FALSE)
pdp_count <- light_effects(fls, v = "NB_PIECES")
plot_counts(p, pdp_count, alpha = 0.3)
pdp_VALEURDESBIENS_REGION <- light_profile(fls_log, v = "VALEUR_DES_BIENS", by = "REGION",
pd_seed = 50, data = df_val, counts_weighted=TRUE)
plot(pdp_VALEURDESBIENS_REGION)
# Weak interaction
pdp_TYPE_RESIDENCE_REGION <- light_profile(fls_log, v = "TYPE_RESIDENCE",
by = "REGION", pd_seed = 50, data = df_val, counts_weighted=TRUE)
plot(pdp_TYPE_RESIDENCE_REGION)
fls